package model

import (
	"time"

	"bmember/pkg/util"
)

const (
	BalanceRecharge       int8 = 1 // 余额充值
	BalanceRechargeRefund int8 = 2 // 充值退款
	BalanceConsum         int8 = 3 // 余额消费
	BalanceConsumRefund   int8 = 4 // 消费退款
	BalanceGift           int8 = 5 // 充值送现金
	BalanceGiftRefund     int8 = 6 // 充值送退款
	BalanceShiftIn        int8 = 7 // 转入

	BalanceConsumStr         = "consumption"        // 余额消费
	BalanceConsumRefundStr   = "consumption_refund" // 消费退款
	BalanceRechargeStr       = "recharge"           // 余额充值
	BalanceRechargeRefundStr = "recharge_refund"    // 充值退款
	BalanceGiftStr           = "gift"               // 充值送现金
	BalanceGiftRefundStr     = "gift_refund"        // 充值送退款
	BalanceShiftInStr        = "shift_in"           // 转入
)

// BalanceLogRemark 余额日志备注
type BalanceLogRemark struct {
	Reason string `json:"reason"`
}

// BalanceLog 余额流水
type BalanceLog struct {
	// id
	Id int64 `json:"id" sql:"id"`
	// 品牌
	BrandId int64 `json:"brand_id" sql:"brand_id"`
	// 门店id 0~品牌
	StoreId int64 `json:"store_id" sql:"store_id"`
	// 体系id
	GroupId int64 `json:"group_id" sql:"group_id"`
	// 卡id
	CardId int64 `json:"card_id" sql:"card_id"`
	// 会员id
	MemberId int64 `json:"member_id" sql:"member_id"`
	// 会员账号id
	AccId int64 `json:"acc_id" sql:"acc_id"`
	// 余额日志类型
	BalType int8 `json:"bal_type" sql:"bal_type"`
	// 金额，精确至分
	Amount int64 `json:"amount" sql:"amount"`
	// 支付单单号
	PayOrderNo string `json:"pay_order_no" sql:"pay_order_no"`
	// 退款单单号
	RefundOrderNo string `json:"refund_order_no" sql:"refund_order_no"`
	// 操作员工id
	EmpId int64 `json:"emp_id" sql:"emp_id"`
	// 备注
	Remark    []byte    `json:"remark" sql:"remark"` // 备注
	CreatedAt time.Time `json:"created_at" sql:"created_at"`
	UpdatedAt time.Time `json:"updated_at" sql:"updated_at"`
	DeletedAt int64     `json:"deleted_at" sql:"deleted_at"`
}

// NewBalanceLog 新建余额记录
func NewBalanceLog(brandId, storeId, groupId, cardId, memberId, accId, empId int64) *BalanceLog {
	now := util.GetNow()
	return &BalanceLog{
		BrandId:   brandId,
		StoreId:   storeId,
		GroupId:   groupId,
		CardId:    cardId,
		MemberId:  memberId,
		Remark:    []byte("{}"),
		AccId:     accId,
		EmpId:     empId,
		CreatedAt: now,
		UpdatedAt: now,
	}
}

// SetAmount 设置金额
func (b *BalanceLog) SetAmount(balType int8, Amount uint64) error {
	switch balType {
	case BalanceConsum, BalanceRechargeRefund, BalanceGiftRefund:
		b.Amount = -int64(Amount)
		b.BalType = balType
	case BalanceConsumRefund, BalanceRecharge, BalanceGift, BalanceShiftIn:
		b.Amount = int64(Amount)
		b.BalType = balType
	default:
		return InvalidEnum
	}
	b.UpdatedAt = util.GetNow()
	return nil
}

// Recharge 充值
// payOrderId 为支付单号，不是订单号
func (b *BalanceLog) Recharge(payOrderNo string, amount uint64) {
	_ = b.SetAmount(BalanceRecharge, amount)
	b.PayOrderNo = payOrderNo
}

// RechargeRefund 充值退款
// payOrderId 退款支付单单号
func (b *BalanceLog) RechargeRefund(payOrderNo, refundOrderNo string, amount uint64) {
	_ = b.SetAmount(BalanceRechargeRefund, amount)
	b.PayOrderNo = payOrderNo
	b.RefundOrderNo = refundOrderNo
}

// Consumption 消费付款
func (b *BalanceLog) Consumption(payOrderNo string, amount uint64) {
	_ = b.SetAmount(BalanceConsum, amount)
	b.PayOrderNo = payOrderNo
}

// ConsumptionRefund 消费退款
func (b *BalanceLog) ConsumptionRefund(payOrderNo, refundOrderNo string, amount uint64) {
	_ = b.SetAmount(BalanceConsumRefund, amount)
	b.PayOrderNo = payOrderNo
	b.RefundOrderNo = refundOrderNo
}

// GetRemark 获取备注信息
func (b *BalanceLog) GetRemark() *BalanceLogRemark {
	ret := &BalanceLogRemark{}
	if b.Remark != nil {
		_ = json.Unmarshal(b.Remark, ret)
	}
	return ret
}

// SetRemark 设置备注
func (b *BalanceLog) SetRemark(r *BalanceLogRemark) {
	if r != nil {
		b.Remark, _ = json.Marshal(r)
		b.UpdatedAt = util.GetNow()
	}
}

// SetReason 设置原因
func (b *BalanceLog) SetReason(r string) {
	if r != "" {
		remark := b.GetRemark()
		remark.Reason = r
		b.SetRemark(remark)
	}
}

// CashGift 赠送金额
func (b *BalanceLog) CashGift(amount uint64, reason string) {
	_ = b.SetAmount(BalanceGift, amount)
	b.SetReason(reason)
}

// CashGiftRefund 赠送退款
func (b *BalanceLog) CashGiftRefund(amount uint64, reason string) {
	_ = b.SetAmount(BalanceGiftRefund, amount)
	b.SetReason(reason)
}

// GetBalType 获得余额日志类型
func (b *BalanceLog) GetBalType() string {
	switch b.BalType {
	case BalanceConsum:
		return BalanceConsumStr
	case BalanceConsumRefund:
		return BalanceConsumRefundStr
	case BalanceRecharge:
		return BalanceRechargeStr
	case BalanceRechargeRefund:
		return BalanceRechargeRefundStr
	case BalanceGift:
		return BalanceGiftStr
	case BalanceGiftRefund:
		return BalanceGiftRefundStr
	case BalanceShiftIn:
		return BalanceShiftInStr
	default:
		return ""
	}
}
